import * as $util from './hc-util.js'

var webhost = $util.webhost;

export function post(url, data) {
    url = webhost + url;
    return axios.post(url, data);
};

export function get(url) {
    url = webhost + url;
    return axios.get(url);
};

function doresponse(callback, url, data) {
    return _do;

    function _do(res) {
        let errorcode = res.data.error;
        if (!errorcode) {
            if (callback) callback(res.data.data);
            return;
        };
        //Unauthenticated
        if (errorcode === 1) {
            // console.info('未登录')
            $util.forward('/admin/login.htm', {
                redirect: document.location.href
            })
        } else if (errorcode === 2) { //AuthorizationException
            $util.forwardToErrorMsg('你没有相应的访问权限，访问此功能之前需要获得管理员授权。', document.location.href);
        } else if (errorcode === 3) { //IncorrectCredentialsException
            $util.forwardToErrorMsg('登录失败，错误的登录名、密码。', document.location.href);
        } else if (errorcode) {
            $util.forwardToErrorMsg('执行出错：' + res.data.data, document.location.href);
        }
        console.error('service error when to access service.', url, data, errorcode, res.data.data);
        return;
    };
};

function doexception(url, data) {
    return _do;

    function _do(ex) {
        console.error('network error when to access web service.', url, data, ex);
        $util.forwardToErrorMsg('网络开小差了：' + ex, document.location.href);
    }
};

export function getdata(url, callback) {
    get(url).then(doresponse(callback, url)).catch(doexception(url));
};

export function postdata(url, data, callback) {
    post(url, data).then(doresponse(callback, url, data)).catch(doexception(url, data));
};

//ruleInf{rtype/rname/rpath}
export function create(ruleInfo, callback) {
    postdata("/manage/create", ruleInfo, callback)
};

export function run(rpath, args, callback) {
    postdata("/manage/run?rpath=" + rpath, args, callback)
};

function loadConfig(callback) {
    console.log('loadConfig is called');
    getdata("/manage/loadConfig", callback)
};

export function loadProject(rpath, callback) {
    getdata("/manage/loadProject?rpath=" + rpath, callback)
};

export function obtainRuleDefByRpath(rpath, callback) {
    getdata("/manage/loadByRpath?rpath=" + rpath, callback)
};

export function projectList(callback) {
    getdata("/manage/projectList", callback)
};

export function check$configOrLoad(callback) {
    if (window.top.$config) {
        window.$config = window.top.$config; //maybe a new window which is not assigned with $config
        // console.log('check$configOrLoad $config exists, neednot load',window.top.$config);
        callback(window.top.$config);
        return; //prevent to load config and call back
    };

    // console.log('check$configOrLoad $config does not exist, load it .');
    loadConfig(function(config) {
        window.top.$config = config;
        window.$config = window.top.$config;
        callback(config);
    })
};

export function updateRuleDefInVm(vm, callback) {
    post('/manage/update', vm.ruleDef)
        .then(function(response) {
            var ret;
            ret = response.data;

            if (ret.error) {
                vm.$message({
                    message: ret.data,
                    type: 'warning'
                });
                return;
            } else {
                vm.$message({
                    message: '保存成功！',
                    type: 'success'
                });
            };

            if (window.top.$pinfo) {
                window.top.$pinfo.update(response.data.data)
            } else {
                console.error('$pinfo does not exist when update the rule of ', vm.ruleDef)
            };
            
            if (callback) {
                callback(response.data.data)
            }else vm.ruleDef = response.data.data;
            // else document.location.reload(true);
        })
        .catch(function(error) {
            vm.$message({
                message: error,
                type: 'warning'
            });

        });
}

export function deleteRuleDefInVm(vm) {
    let ruleDef = vm.ruleDef;
    let withvm = window.top.vm ? window.top.vm : vm;
    withvm.$confirm('此操作将永久删除该决策组件的全部内容, 是否继续?', '提示', {
        cancelButtonText: '取消',
        confirmButtonText: '确定',
        type: 'warning',
        center: true
    }).then(
        () => {
            doDelete();
        }
    ).catch(
        () => {}
    );

    function doDelete() {
        post('/manage/delete?rpath=' + ruleDef.rpath)
            .then(function(response) {
                let ret = response.data;

                if (ret.error) {
                    withvm.$message({
                        message: ret.data,
                        type: 'warning'
                    });
                    return;
                } else {
                    withvm.$message({
                        message: '删除成功！',
                        type: 'success'
                    });
                }

                if (window.top.$pinfo) {
                    window.top.$pinfo.remove(ruleDef)
                } else {
                    console.error('$pinfo does not exist when delete the rule of ', ruleDef)
                }

                // close tab or forward to welcome page
                if (window.top.$workbench) {
                    window.top.$workbench.closePage('rpath@' + ruleDef.rpath);
                    window.top.$workbench.refreshPage('rtype@' + ruleDef.rtype);
                } else document.location.href = webhost + '/welcome.htm';

            })
            .catch(function(error) {
                withvm.$message({
                    message: error,
                    type: 'warning'
                });
            });
    }

};

//args: callback({$pinfo,$config})
export function check$pinfoOrLoad(callback, projectRpath) {
    let rpath = window.top.$pinfo ? window.top.$pinfo.rpath : projectRpath;

    load$pinfo(rpath, callback, false)
}

export function load$pinfo(projectRpath, callback, forceRefresh = false) {
    if (!projectRpath) {
        console.error('no project rpath arguments when load$pinfo,to clean the current project info.');
        assignToGlobalVariable({
            $pinfo: null,
            $config: window.top.$config
        })
        return;
    }

    if ((projectRpath === (window.top.$pinfo || {}).rpath) && !forceRefresh) {
        assignToGlobalVariable(window.top);
        return;
    };

    if (!window.top.$config) {
        console.warn('no configuration info when to load $pinfo,will be re-loaded again');
        loadConfig(function(config) {
            window.top.$config = config;
            _loadProject()
        })
    } else _loadProject();

    return;

    function _loadProject() {
        loadProject(projectRpath, function(projectinfo) {
            enhance$pinfo(projectinfo)
            assignToGlobalVariable({
                $pinfo: projectinfo,
                $config: window.top.$config
            });
        });
    };

    function enhance$pinfo(pinfo) {
        pinfo.rulePathMap = {};
        // pinfo.ruleIdMap = {};
        pinfo.pcode = pcode.bind(pinfo);

        pinfo.ruleList.forEach(it => {
            // pinfo.ruleIdMap[it.rid] = it;
            pinfo.rulePathMap[it.rpath] = it;
            // TODO append into the new rule from add/update/remove method
            it.rcode = rcode.bind(it);
        });

        pinfo.add = add.bind(pinfo);
        pinfo.update = update.bind(pinfo);
        pinfo.remove = remove.bind(pinfo);
    };

    function pcode() {
        let dot = this.rpath.indexOf("/");
        return dot == -1 ? this.rpath : this.rpath.substr(0, dot)
    };

    function rcode() {
        let dot = this.rpath.lastIndexOf("/");
        return dot == -1 ? this.rpath : this.rpath.substr(dot + 1)
    };

    function assignToGlobalVariable(data) {
        let win = window.top;
        win.$pinfo = data.$pinfo;
        win.$config = data.$config;

        // link to current window for easy use
        window.$pinfo = data.$pinfo;
        window.$config = data.$config;

        if (callback) callback(data);
    };

    function add(ruleDef) {
        this.ruleList.push(ruleDef);
        this.rulePathMap[ruleDef.rpath] = ruleDef;
        // this.ruleIdMap[ruleDef.rid] = ruleDef;
    };

    function update(ruleDef) {
        let index = this.ruleList.findIndex(it => it.rpath == ruleDef.rpath);
        if (index < 0) {
            console.error('the rule does not exist when updating.', ruleDef)
            return;
        }
        this.ruleList[index] = ruleDef;

        this.rulePathMap[ruleDef.rpath] = ruleDef;
        // this.ruleIdMap[ruleDef.rid] = ruleDef;

    };

    function remove(ruleDef) {
        let key = ruleDef;
        if (typeof(key) == 'object') key = key.rpath;
        let index;
        if (typeof(key) == 'string') {
            index = this.ruleList.findIndex(it => it.rpath == key);
            // } else if (typeof(key) == 'number') {
            // index = this.ruleList.findIndex(it => it.rid == key);
        } else {
            console.error('wrong argument when to remove the rule of [] from $pinfo ', ruleDef)
            return;
        };

        this.ruleList.splice(index, 1);

        delete this.rulePathMap[ruleDef.rpath];
        // delete this.ruleIdMap[ruleDef.rid]
    };
};
